﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows.Forms;
using System.Xml.Linq;

namespace BackupRestoreSoftwares
{
    public partial class frmCheck : Form
    {
        private readonly Queue<string> _downloadUrls = new Queue<string>();
        private readonly ManualResetEvent ma = new ManualResetEvent(false);
        private readonly string path_dir = Application.StartupPath + @"\";
        private string url = "https://softpc86vn.googlecode.com/svn/update/Backup-Restore/update-info.xml";

        public frmCheck()
        {
            InitializeComponent();
            BackColor = Color.FromArgb(45, 45, 48); // màu đen
            if (File.Exists(path_dir + @"loader-update.exe"))
            {
                File.Delete(path_dir + @"loader-update.exe");
            }
        }

        public string GetNewVersion { get; set; }
        public static string GetLinkMain { get; set; }
        public string GetListFile { get; set; }
        public static string GetRarFiles { get; set; }
        public string GetName { get; set; }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            lbl_checkup.Invoke((Action) (() => lbl_checkup.Text = "Connecting server..."));
            pic_load.Invoke((Action) (() => pic_load.Visible = true));

            if (CheckUpdate(url))
            {
                string ver_old = "0";
                try
                {
                    ver_old = ProductVersion;
                }
                catch
                {
                    ver_old = "0.0.0.0";
                }
                string ver_new = GetNewVersion;

                ver_new.CompareTo(ver_old); // So sánh 2 phiên bản
                if (ver_new.CompareTo(ver_old) > 0)
                {
                    ma.Reset();
                    // Invoke == tạm hiểu là ủy quyền can thiệp vào ứng dụng
                    lbl_checkup.Invoke((Action) (() => lbl_checkup.Text = "Connect Successfull !"));
                    pic_load.Invoke((Action) (() => pic_load.Visible = false));
                    pic_fis.Invoke((Action) (() => pic_fis.Visible = true));
                    lbl_download.Invoke((Action) (() => lbl_download.Text = "Updatting new version ..."));
                    pic_load2.Invoke((Action) (() => pic_load2.Visible = true));

                    downloadFile(GetListFile.Split(';'));
                    ma.WaitOne();

                    lbl_download.Invoke((Action) (() => lbl_download.Text = "Update Successfull !"));
                    pic_load2.Invoke((Action) (() => pic_load2.Visible = false));
                    pic_fis2.Invoke((Action) (() => pic_fis2.Visible = true));
                    lbl_dl_file.Invoke((Action) (() => lbl_dl_file.Text = "You are using newest version."));
                    pic_load3.Invoke((Action) (() => pic_load3.Visible = false));
                    pic_fis3.Invoke((Action) (() => pic_fis3.Visible = true));
                }
                else
                {
                    lbl_checkup.Invoke((Action) (() => lbl_checkup.Text = "Connect Successfull !"));
                    pic_load.Invoke((Action) (() => pic_load.Visible = false));
                    pic_fis.Invoke((Action) (() => pic_fis.Visible = true));
                    Thread.Sleep(500);
                    lbl_download.Invoke((Action) (() => lbl_download.Text = "Not found new version."));
                    pic_load2.Invoke((Action) (() => pic_load2.Visible = true));
                    pic_load2.Invoke((Action) (() => pic_load2.Visible = false));
                    pic_fis2.Invoke((Action) (() => pic_fis2.Visible = true));
                    Thread.Sleep(100);
                    lbl_dl_file.Invoke((Action) (() => lbl_dl_file.Text = "You are using newest version."));
                    pic_load3.Invoke((Action) (() => pic_load3.Visible = false));
                    pic_fis3.Invoke((Action) (() => pic_fis3.Visible = true));
                }
            }
            else
            {
                lbl_checkup.Invoke((Action) (() => lbl_checkup.Text = "Not connect server!"));
                pic_load.Invoke((Action) (() => pic_load.Visible = false));
                pic_fis.Invoke((Action) (() => pic_fis.Visible = true));
                //Thread.Sleep(00);
                lbl_download.Invoke((Action) (() => lbl_download.Text = "Not found new version."));
                pic_load2.Invoke((Action) (() => pic_load2.Visible = true));
                pic_load2.Invoke((Action) (() => pic_load2.Visible = false));
                pic_fis2.Invoke((Action) (() => pic_fis2.Visible = true));
                //Thread.Sleep(1000);
                lbl_dl_file.Invoke((Action) (() => lbl_dl_file.Text = "You are using newest version."));
                pic_load3.Invoke((Action) (() => pic_load3.Visible = false));
                pic_fis3.Invoke((Action) (() => pic_fis3.Visible = true));
            }
            Thread.Sleep(1000);
            lbl_start.Invoke((Action) (() => lbl_start.Text = "Starting program ..."));
            pic_load4.Invoke((Action) (() => pic_load4.Visible = true));
            Thread.Sleep(500);
            pic_load4.Invoke((Action) (() => pic_load4.Visible = false));
            pic_fis4.Invoke((Action) (() => pic_fis4.Visible = true));
            Thread.Sleep(500);

            if (File.Exists(path_dir + @"\loader-update.exe"))
            {
                Process.Start("loader-update.exe");
                Process.GetCurrentProcess().Kill();
            }
            else
            {
                var frm = new frmMain();
                pic_fis4.Invoke((Action) (() => frm.Show()));
                pic_fis4.Invoke((Action) (() => Hide()));
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (!backgroundWorker1.CancellationPending)
            {
                //lblPercent.Text = e.ProgressPercentage + "%";
                //progressBar1.PerformStep();
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }

        private bool CheckUpdate(String URL)
        {
            try
            {
                XElement sitemap = XElement.Load(url);
                if (sitemap.HasElements)
                {
                    GetNewVersion = sitemap.Element("version").Value;
                    GetLinkMain = sitemap.Element("link").Value;
                    GetListFile = sitemap.Element("app").Value;
                    GetRarFiles = sitemap.Element("rar").Value;
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        private void downloadFile(IEnumerable<string> urls)
        {
            foreach (string url in urls)
            {
                _downloadUrls.Enqueue(url);
            }
            DownloadFile(GetLinkMain, path_dir);
        }

        private void DownloadFile(string ur, string pathur)
        {
            if (_downloadUrls.Any())
            {
                var client = new WebClient();
                client.DownloadProgressChanged += client_DownloadProgressChanged;
                client.DownloadFileCompleted += client_DownloadFileCompleted;

                string url = _downloadUrls.Dequeue();
                string FileName = url.Substring(url.LastIndexOf("/") + 1,
                    (url.Length - url.LastIndexOf("/") - 1));
                GetName = FileName;
                client.DownloadFileAsync(new Uri(ur + url), pathur + FileName);
                pic_load3.Invoke((Action) (() => pic_load3.Visible = true));
                return;
            }
            ma.Set(); // kết thúc tải
        }

        private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                // handle error scenario
                throw e.Error;
            }
            if (e.Cancelled)
            {
                // handle cancelled scenario
            }
            DownloadFile(GetLinkMain, path_dir);
        }

        private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            double bytesIn = double.Parse(e.BytesReceived.ToString());
            double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
            lbl_dl_file.Invoke(
                (Action)
                    (() =>
                        lbl_dl_file.Text =
                            "Downloading: " + GetName + " | Size: " + (bytesIn/1048576).ToString().Substring(0, 4) +
                            " / " + (totalBytes/1048576).ToString().Substring(0, 4) + " MB"));
        }

        private void frmCheck_Load(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }
    }
}